#include "crestrictedareasupervisor.h"
#include <QMessageBox>

CRestrictedAreaSupervisor::CRestrictedAreaSupervisor(IVSModel* _ivsModel) :
    IVSControllerBase(_ivsModel)
{
    currentState = INVALID;
    lastState = INVALID;
}

void CRestrictedAreaSupervisor::run()
{
    if(initialize())
    {
        IplImage* frame = cvQueryFrame(capture);
        char key;
        isRunning = true;

        /* init */
        videoPlaySpeedBoost = 10;
        IplImage* grayFrame  = cvCreateImage(size, IPL_DEPTH_8U, 1);
        IplImage* runningAvg = cvCreateImage(size, IPL_DEPTH_32F, 1);
        IplImage* background = cvCreateImage(size, IPL_DEPTH_8U, 1);
        IplImage* diffImage  = cvCreateImage(size, IPL_DEPTH_8U, 1);

        cvCvtColor(frame, grayFrame, CV_RGB2GRAY);
        applyROIMask(grayFrame);
        cvCopy(grayFrame, background);
        cvCvtScale(grayFrame, runningAvg);

        int nInitBGFrame = 0; // No of frame to init BG
        int count = 0;
        bool bSwitchColor;
        while(frame && isRunning){
            cvCvtColor(frame, grayFrame, CV_RGB2GRAY);
            applyROIMask(grayFrame);

            if(nInitBGFrame++ < ivsModel->RestrictedAreaSurvuillanceSettings().noFrameToInitBackground) {
                cvRunningAvg(grayFrame,
                             runningAvg,
                             1.0/ivsModel->RestrictedAreaSurvuillanceSettings().noFrameToInitBackground);
            }else{
                cvRunningAvg(grayFrame,
                             runningAvg,
                             ivsModel->RestrictedAreaSurvuillanceSettings().alpha);
                cvCvtScale(runningAvg, background);
                cvAbsDiff(grayFrame, background, diffImage);

                showDebugImage(background, "background");
                showDebugImage(diffImage, "difference image");

                smartThreshold(diffImage, ivsModel->RestrictedAreaSurvuillanceSettings().noBin);
                showDebugImage(diffImage, "object mask");

                //Find the contours of the moving images in the frame.
                CvMemStorage* storage = cvCreateMemStorage(0);
                CvSeq* contour = 0;
                cvFindContours( diffImage, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

                //Process each moving contour in the current frame...
                CvPoint pt1, pt2;
                currentState = NORMAL;
                for( ; contour != 0; contour = contour->h_next ){
                    //Get a bounding rectangle around the moving object.
                    CvRect bndRect = cvBoundingRect(contour, 0);
                    if(bndRect.height*bndRect.width < (int)ivsModel->RestrictedAreaSurvuillanceSettings().bnRectArea_min ||
                            bndRect.height*bndRect.width > (int)ivsModel->RestrictedAreaSurvuillanceSettings().bnRectArea_max )
                        continue;

                    pt1.x = bndRect.x;
                    pt1.y = bndRect.y;
                    pt2.x = bndRect.x + bndRect.width;
                    pt2.y = bndRect.y + bndRect.height;
                    if(ivsModel->VerboseLevel() >= 1)
                        cvRectangle(frame, pt1, pt2, cvScalar(0,0,255),2,8,0);
                    if(ivsModel->VerboseLevel() >= 2){
                        if(bSwitchColor)
                            cvAddS(frame, cvScalar(0,0,255), frame, diffImage);
                        else
                            cvAddS(frame, cvScalar(0,255,0), frame, diffImage);
                        bSwitchColor = !bSwitchColor;
                    }

                    currentState = INTRUDER_DETECTED;
                }
                cvReleaseMemStorage(&storage);

                showMainImage(frame);
                if(currentState !=  lastState){
                    if(count++ > ivsModel->RestrictedAreaSurvuillanceSettings().stateChangeDelay){
                        if(currentState == INTRUDER_DETECTED)
                            emit stateChanged("Poeple enter the restricted area", Qt::red);
                        else if(currentState == NORMAL)
                            emit stateChanged("Secure", Qt::blue);

                        lastState = currentState;
                        count = 0;
                    }
                }else
                    count = 0;
            }

            key = cvWaitKey(1000/fps);
            if(key == 'r')
                setupROI();

            frame = cvQueryFrame(capture);
        }
        qWarning("stoped");

        /* release */
        cvReleaseImage(&grayFrame);
        cvReleaseImage(&runningAvg);
        cvReleaseImage(&background);
        cvReleaseImage(&diffImage);
    }else
    {
        QMessageBox::warning(0,
                             "Unable to play the video",
                             "Can not capture from the video source. ",
                             QMessageBox::Ok);
    }
}

void CRestrictedAreaSupervisor::stop()
{
    isRunning = false;
    release();
}

void CRestrictedAreaSupervisor::showMainImage(IplImage *img)
{

    IVSControllerBase::showMainImage(img);
}

void CRestrictedAreaSupervisor::release()
{
    //TODO: add your new releases here

    IVSControllerBase::release();
}
